<?php

namespace Core\Application;

use Core\Http\Response;
use Core\Config\Config;
use Core\Database\Configuration as DbConfiguration;
use Core\Support\Redis;

class App
{
    /**
     * 运行配置文件
     */
    protected $runConfig;

    public function __construct($config)
    {
        $this->runConfig = $config;

        //异常和错误处理
        // $this->setExceptionHandler();
        // $this->setErrorHandler();
        // $this->registerShutdownFunction();

        // 设置一些运行配置
        $this->loadEnv();
        $this->loadConfig();
        $this->setRunOption();
        $this->bootLoader();
    }

    /**
     * 默认在fpm中运行
     */
    public function run()
    {
        $this->run_fpm();
    }

    /**
     * 在fpm中运行
     */
    public function run_fpm()
    {
        $routes = $this->getRoutes();

        $fpm = new RunFpm(['routes' => $routes]);
        $fpm->run();
    }

    /**
     * 在swoole中运行
     */
    public function run_swoole()
    {
        $routes = $this->getRoutes();

        $swoole = new RunSwoole(['routes' => $routes]);
        $swoole->run();
    }

    /**
     * 获取路由配置
     */
    protected function getRoutes()
    {
        $routes = [];
        foreach ($this->runConfig as $key => $item) {
            $routes[] = $item['route'];
        }

        return $routes;
    }

    /**
     * 设置PHP运行环境
     */
    protected function setRunOption()
    {
        ini_set('display_errors', 0);
        ini_set('error_reporting', E_ALL);

        // debug模式将错误信息作为输出的一部分打印到屏幕
        if (env('APP_DEBUG') === 'true') {
            ini_set('display_errors', 1);
        }

        // 设置时区
        $time_zone = Config::get('app.time_zone');
        if ($time_zone) {
            date_default_timezone_set($time_zone);
        }
    }

    /**
     * 启动加载
     */
    protected function bootLoader()
    {
        // 注册数据库配置信息
        DbConfiguration::loadConfig(Config::get('database'));
        // 注册Redis配置信息
        Redis::loadConfig(Config::get('database'));
    }

    /**
     * load env
     */
    protected function loadEnv()
    {
        $dotenv = \Dotenv\Dotenv::createImmutable(APP_HOME);
        $dotenv->load();
    }

    /**
     * load config 目录下的配置文件
     * todo: 生产环境可以优化cache
     */
    protected function loadConfig()
    {
        Config::load(APP_HOME . '/config');
    }

    /**
     * 异常处理函数 (swoole 不支持)
     */
    protected function setExceptionHandler()
    {
        set_exception_handler(function (\Exception $e) {

            // add to log

            $response = new Response();
            $response->fail(600100, $e->getMessage())->send();
        });
    }

    /**
     * 错误处理函数 (swoole 不支持)
     */
    protected function setErrorHandler()
    {
        set_error_handler(function ($errno, $errstr, $errfile, $errline) {
            // echo "error_handler: errno: " . $errno . PHP_EOL;
            // echo "error_handler: errstr: " . $errstr . PHP_EOL;
            // echo "error_handler: errfile: " . $errfile . PHP_EOL;
            // echo "error_handler: errline: " . $errline . PHP_EOL;
            // 丢给异常, 让异常去处理

            throw new \Exception($errstr);
        });
    }

    /**
     * 注册一个会在php中止时执行的函数 (swoole 不支持)
     */
    protected function registerShutdownFunction()
    {
        register_shutdown_function(function () {
            $error = error_get_last();
            if ($error) {
                echo '注册一个会在php中止时执行的函数 </br>', PHP_EOL;
                // debug_print_backtrace(0, 5);
                // print_r($error);

                throw new \Exception("shut down function");
            }
            return true;
        });
    }
}
